// 标签打印 指令集
import {
	TextEncoder,
	TextDecoder
} from '@/utils/text-encoding';

/** 创建标签打印机 */
export function createGprinter() {
	// 创建实例并挂载
	const instance = new Object();
	instance.name = "标签打印机";

	// 打印指令数据集
	let commandArray = [];
	// 需要特别注意，在每一条指令结尾需要加入换行符，即字符串“\r\n”或 16进制 0x0D 0x0A
	const newlineString = '\r\n';
	// const newlineHexadecimal = '0x0D 0x0A';

	/** 挂载方法：创建新的打印对象
	 */
	instance.createNew = function() {
		commandArray = [];
		return instance;
	};

	/** 挂载方法：将指令转成数组后装入打印指令数据集
	 * @param content 指令字符串
	 * @param newline 是否换行
	 */
	instance.addCommand = function(content, newline = true) {
		if (newline === true && content.endsWith(newlineString) === false) {
			content = `${content}${newlineString}`;
		}
		const code = new TextEncoder(
			'gb18030', {
				NONSTANDARD_allowLegacyEncoding: true
			}).encode(content)
		for (let i = 0; i < code.length; ++i) {
			commandArray.push(code[i]);
		}
	};
	/** 挂载方法：获取打印指令数据集
	 */
	instance.getCommand = function() {
		return commandArray;
	};

	function intToByte(i) {
		// 此处关键 -- android是java平台 byte数值范围是 [-128, 127]
		// 因为java平台的byte类型是有符号的 最高位表示符号，所以数值范围固定
		// 而图片计算出来的是数值是 0 -255 属于int类型
		// 所以把int 转换成byte类型 
		//#ifdef APP-PLUS
		var b = i & 0xFF;
		var c = 0;
		if (b >= 128) {
			c = b % 128;
			c = -1 * (128 - c);
		} else {
			c = b;
		}
		return c
		//#endif
		// 而微信小程序不需要，因为小程序api接收的是 无符号8位
		//#ifdef MP-WEIXIN
		return i
		//#endif
	}

	/** 挂载方法：设定卷标纸的宽度和长度
	 * (1) 英制系统(inch) SIZE m,n 
	 * (2) 公制系统(mm) SIZE m mm,n mm
	 * @param width m 标签纸的宽度(不含背纸)
	 * @param height n 标签纸的长度(不含背纸)
	 * @param inch 是否英制系统(inch)，默认 false
	 */
	instance.size = function(width, height, inch = false) {
		let data = '';
		if (inch === true) {
			data = `SIZE ${width},${height}`;
		} else {
			data = `SIZE ${width} mm,${height} mm`;
		}
		instance.addCommand(data);
	};

	/** 挂载方法：产生钱箱控制脉冲
	 * CASHDRAWER m,t1,t2
	 * ESC p m,t1,t2
	 * @param m [0，48 钱箱插座的引脚 2] [1，49 钱箱插座的引脚 5]
	 * @param t1 0≤t1≤255，输出由 t1 设定的钱箱开启脉冲到由 m 指 定的引脚
	 * @param t2 0≤t2≤255，输出由 t2 设定的钱箱开启脉冲到由 m 指 定的引脚
	 */
	instance.cashdrawer = function(m, t1, t2) {
		const data = `CASHDRAWER ${m},${t1},${t2}${newlineString}ESC p ${m},${t1},${t2}`;
		instance.addCommand(data);
	};

	/** 挂载方法：定义两张卷标纸间的垂直间距距离
	 * (1) 英制系统(inch) GAP m,n 
	 * (2) 公制系统(mm) GAP m mm,n mm
	 * @param m 两标签纸中间的垂直距离，0≤m≤1(inch)，0≤m≤25.4(mm)
	 * @param n 垂直间距偏移，n≤标签纸纸张长度(inch 或 mm)
	 * @param inch 是否英制系统(inch)，默认 false
	 */
	instance.gap = function(m, n, inch = false) {
		let data = '';
		if (inch === true) {
			data = `GAP ${m},${n}`;
		} else {
			data = `GAP ${m} mm,${n} mm`;
		}
		instance.addCommand(data);
	};

	/** 挂载方法：设定黑标高度及定义标签印完后标签额外送出的长度
	 * (1) 英制系统(inch) BLINE m,n
	 * (2) 公制系统(mm) BLINE m mm,n mm
	 * 注:以上指令发送后，GAP 指令无效，自检页信息 GAP 6 mm、BLINE 3 mm
	 * @param m 黑标高度，0≤m≤1(inch)，0≤m≤25.4(mm)
	 * @param n 额外送出纸张长度，n≤标签纸纸张长度(inch 或 mm)
	 * @param inch 是否英制系统(inch)，默认 false
	 */
	instance.bline = function(m, n, inch = false) {
		let data = '';
		if (inch === true) {
			data = `BLINE ${m},${n}`;
		} else {
			data = `BLINE ${m} mm,${n} mm`;
		}
		instance.addCommand(data);
	};

	/** 挂载方法：用于控制在剥离模式时(peel-off mode)每张卷标停止的位置，在打印 下一张时打印机会将原先多推出或少推出的部分以回拉方式补偿回来。
	 * (1) 英制系统(inch) OFFSET m
	 * (2) 公制系统(mm) OFFSET m mm
	 * 注:该指令仅 适用于剥离模式。
	 * @param m 纸张停止的距离(inch 或 mm)，0 ≤ m ≤ 1(inch)，0 ≤ m ≤ 25.4(mm)
	 * @param inch 是否英制系统(inch)，默认 false
	 */
	instance.offset = function(m, inch = false) {
		let data = '';
		if (inch === true) {
			data = `OFFSET ${m}`;
		} else {
			data = `OFFSET ${m} mm`;
		}
		instance.addCommand(data);
	};

	/** 挂载方法：控制打印速度
	 * SPEED n
	 * @param n 设定打印速度为 n"/sec
	 */
	instance.speed = function(n) {
		const data = `SPEED ${n}`;
		instance.addCommand(data);
	};

	/** 挂载方法：控制打印时的浓度
	 * DENSITY n
	 * @param n 0~15，0:使用最淡的打印浓度，15:使用最深的打印浓度
	 */
	instance.density = function(n) {
		const data = `DENSITY ${n}`;
		instance.addCommand(data);
	};

	/** 挂载方法：定义打印时出纸和打印字体的方向
	 * DIRECTION n
	 * @param n 0 或 1，正出纸或反出纸
	 */
	instance.direction = function(n) {
		const data = `DIRECTION ${n}`;
		instance.addCommand(data);
	};

	/** 挂载方法：定义卷标的参考坐标原点。坐标原点 位置和打印方向有关
	 * REFERENCE x,y
	 * @param x 水平方向的坐标位置,单位 dot
	 * @param y 垂直方向的坐标位置,单位 dot
	 */
	instance.reference = function(x, y) {
		const data = `REFERENCE ${x},${y}`;
		instance.addCommand(data);
	};

	/** 挂载方法：选择对应的国际字符集
	 * COUNTRY n
	 * @param n 001:USA
				002:French
				003:Latin America
				034:Spanish
				039:Italian
				044:United Kingdom
				046:Swedish
				047:Norwegian
				049:German
	 */
	instance.country = function(n) {
		const data = `COUNTRY ${n}`;
		instance.addCommand(data);
	};

	/** 挂载方法：选择对应的国际代码页
	 * CODEPAGE n
	 * @param n 8-bit codepage 字符集代表
				437:United States
				850:Multilingual
				852:Slavic
				860:Portuguese
				863:Canadian/French
				865:Nordic
				Windows code page
				1250:Central Europe
				1252:Latin I
				1253:Greek
				1254:Turkish
				以下代码页仅限于 12×24 dot 英数字体 WestEurope:WestEurope
				Greek:Greek
				Hebrew:Hebrew
				EastEurope:EastEurope
				Iran:Iran
				IranII:IranII
				Latvian:Latvian
				Arabic:Arabic
				Vietnam:Vietnam
				Uygur:Uygur
				Thai:Thai
				1252:Latin I
				1257:WPC1257
				1251:WPC1251
				866:Cyrillic
				858:PC858
				747:PC747
				864:PC864
				1001:PC1001
	 */
	instance.codepage = function(n) {
		const data = `CODEPAGE ${n}`;
		instance.addCommand(data);
	}

	/** 挂载方法：清除图像缓冲区(image buffer)的数据
	 * CLS
	 * 注:此项指令必须置于 SIZE 指令之后
	 */
	instance.cls = function() {
		const data = `CLS`;
		instance.addCommand(data);
	};

	/** 挂载方法：将标签纸向前推送指定的长度
	 * FEED n
	 * @param n 1≤n≤9999，单位 dot
	 */
	instance.feed = function(n) {
		const data = `FEED ${n}`;
		instance.addCommand(data);
	};

	/** 挂载方法：将标签纸向后回拉指定的长度
	 * BACKFEED n
	 * @param n 1≤n≤9999，单位 dot
	 */
	instance.backFeed = function(n) {
		const data = `BACKFEED ${n}`;
		instance.addCommand(data);
	};
	/** 挂载方法：将标签纸向后回拉指定的长度
	 * BACKUP n
	 * @param n 1≤n≤9999，单位 dot
	 */
	instance.backup = function(n) {
		const data = `BACKUP ${n}`;
		instance.addCommand(data);
	};

	/** 挂载方法：控制打印机进一张标签纸
	 * FORMFEED
	 */
	instance.formfeed = function(n) {
		const data = `FORMFEED`;
		instance.addCommand(data);
	};

	/** 挂载方法：在使用含有间隙或黑标的标签纸时，若不能确定第一张标签纸是否在正确打印位置时，
	 *  此指令可将标签纸向前推送至下一张标签纸的起点开始打印。标签尺寸和间隙需要在本条指令前设置。
	 * HOME
	 */
	instance.home = function() {
		const data = `HOME`;
		instance.addCommand(data);
	};

	/** 挂载方法：打印出存储于影像缓冲区内的数据
	 * PRINT m[,n]
	 * @param m 指定打印的份数(set)，1≤m≤65535
	 * @param n 每张标签需重复打印的张数，1≤n≤65535
	 */
	instance.print = function(m = 1, n = 1) {
		const data = `PRINT ${m},${n}`;
		instance.addCommand(data);
	};

	/** 挂载方法：控制蜂鸣器的频率，可设定 10 阶的声音，每阶声音的长短由第二个 参数控制
	 * SOUND level interval
	 * @param level 音阶:0-9
	 * @param interval 间隔时间:1-4095
	 */
	instance.sound = function(level, interval) {
		const data = `SOUND ${level},${interval}`;
		instance.addCommand(data);
	};

	/** 挂载方法：设定打印机进纸时，若经过所设定的长度仍无法侦测到垂直间距，则打印机发生错误，停止进纸。
	 * (1) 英制系统(inch) LIMITFEED n
	 * (2) 公制系统(mm) LIMITFEED n mm
	 * 注:该项设定会存于打印机内存 当打印机初始化时，该设定值会被定为 4 inch
	 * @param n 可使用 inch 或 mm
	 * @param inch 是否英制系统(inch)，默认 false
	 */
	instance.limitfeed = function(n, inch = false) {
		let data = '';
		if (inch === true) {
			data = `LIMITFEED ${n}`;
		} else {
			data = `LIMITFEED ${n} mm`;
		}
		instance.addCommand(data);
	};

	/**************************************卷标内容设计指令**************************************/

	/** 挂载方法：在标签上画线
	 * BAR x,y,width,height
	 * @param x 线条左上角 X 坐标，单位 dot
	 * @param y 线条左上角 Y 坐标，单位 dot
	 * @param width 线宽，单位 dot
	 * @param height 线高，单位 dot
	 */
	instance.bar = function(x, y, width, height) {
		const data = `BAR ${x},${y},${width},${height}`;
		instance.addCommand(data);
	};

	/** 挂载方法：画一维条码
	 * BARCODE x,y,"code type",height,human readable,rotation,narrow,wide,"content"
	 * @param content 一维码内容
	 * @param x 左上角水平坐标起点，以点(dot)表示
	 * @param y 左上角垂直坐标起点，以点(dot)表示
	 * @param height 条形码高度，以点(dot)表示
	 * @param readable 0 表示人眼不可识，1 表示人眼可识
	 * @param codeType 一维码类型
	 * @param narrow 窄 bar 宽度，以点(dot)表示
	 * @param wide 宽 bar 宽度，以点(dot)表示
	 * @param rotation 条形码旋转角度，顺时针方向
	 */
	instance.barCode = function(content, x = 0, y = 0, height = 64, readable = 1, codeType = '128', narrow = 1,
		wide = 1, rotation = 0) {
		const data =
			`BARCODE ${x},${y},"${codeType}",${height},${readable},${rotation},${narrow},${wide},"${content}"`;
		instance.addCommand(data);
	};

	/** 挂载方法：在卷标上绘制矩形方框
	 * BOX x_start,y_start,x_end,y_end,line thickness
	 * @param x_start 方框左上角 X 坐标，单位 dot
	 * @param y_start 方框左上角 Y 坐标，单位 dot
	 * @param x_end 方框右下角 X 坐标，单位 dot
	 * @param y_end 方框右下角 Y 坐标，单位 dot
	 * @param line_thickness 方框线宽，单位 dot
	 */
	instance.box = function(x_start, y_start, x_end, y_end, line_thickness) {
		const data = `BOX ${x_start},${y_start},${x_end},${y_end},${line_thickness}`;
		instance.addCommand(data);
	};

	/** 挂载方法：在卷标上绘制图片(根据 canvas 画布参数)
	 * BITMAP x,y,width,height,mode,bitmap data
	 * @param res canvas 画布参数
	 * @param x 位图左上角 X 坐标
	 * @param y 位图左上角 Y 坐标
	 * @param mode 位图绘制模式：0 - OVERWRITE、1 - OR、2 - XOR
	 */
	instance.setBitmap = function(res, x = 0, y = 0, mode = 1) {
		var w = res.width;
		var width = parseInt((res.width + 7) / 8 * 8 / 8);
		var height = res.height;
		// console.log(width + "--" + height);
		// data = "BITMAP " + x + "," + y + "," + width + "," + height + "," + mode + ","
		const data = `BITMAP ${x},${y},${width},${height},${mode},`;
		instance.addCommand(data, false);
		var r = [];
		var bits = new Uint8Array(height * width);
		for (y = 0; y < height; y++) {
			for (x = 0; x < w; x++) {
				let r = res.data[(y * w + x) * 4];
				let g = res.data[(y * w + x) * 4 + 1];
				let b = res.data[(y * w + x) * 4 + 2];
				let a = res.data[(y * w + x) * 4 + 3];
				var color = ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF) <<
					0);
				if ((color & 0xFF) > 128) {
					bits[parseInt(y * width + x / 8)] |= (0x80 >> (x % 8));
				}
			}
		}
		for (var i = 0; i < bits.length; i++) {
			//command.push((~bits[i]) & 0xFF);
			commandArray.push(intToByte(bits[i]));
			//r.push((~bits[i]) & 0xFF);
		}
	};

	/** 挂载方法：在卷标上绘制图片(根据 canvas 画布参数) 
	 * 固定灰度阈值（128以上的都看作白色）
	 * BITMAP x,y,width,height,mode,bitmap data
	 * @param res canvas 画布参数
	 * @param x 位图左上角 X 坐标
	 * @param y 位图左上角 Y 坐标
	 * @param mode 位图绘制模式：0 - OVERWRITE、1 - OR、2 - XOR
	 */
	instance.setBitmapFix = function(res, x = 0, y = 0, mode = 1) {
		var width = parseInt((res.width) / 8 * 8 / 8);
		var height = res.height;
		var imgWidth = res.width;
		var time = 1;
		var temp = res.data.length - width * 32;
		var pointList = [];
		var resultData = [];
		// console.log(width + "--" + height);
		// const data = "BITMAP " + x + "," + y + "," + width + "," + height + "," + mode + ","
		const data = `BITMAP ${x},${y},${width},${height},${mode},`;
		instance.addCommand(data, false);
		//console.log(res.data)
		// console.log('---以上是原始数据---');

		//for循环顺序不要错了，外层遍历高度，内层遍历宽度，因为横向每8个像素点组成一个字节
		for (var y = 0; y < height; y++) {
			for (var x = 0; x < imgWidth; x++) {
				let r = res.data[(y * imgWidth + x) * 4];
				let g = res.data[(y * imgWidth + x) * 4 + 1];
				let b = res.data[(y * imgWidth + x) * 4 + 2];
				let a = res.data[(y * imgWidth + x) * 4 + 3];
				//console.log(`当前${y}行${x}列像素,rgba值:(${r},${g},${b},${a})`)
				// 像素灰度值
				let grayColor = r * 0.299 + g * 0.587 + b * 0.114;
				//灰度值大于128位 
				//1不打印, 0打印 （参考：佳博标签打印机编程手册tspl）
				if (grayColor > 128) {
					pointList.push(1);
				} else {
					pointList.push(0);
				}
			}
		}
		//console.log(pointList)
		for (var i = 0; i < pointList.length; i += 8) {
			var p = pointList[i] * 128 + pointList[i + 1] * 64 + pointList[i + 2] * 32 + pointList[i +
					3] * 16 + pointList[i + 4] * 8 + pointList[i + 5] * 4 + pointList[i + 6] * 2 +
				pointList[i + 7];
			resultData.push(p);
		}
		// console.log('最终数据：', resultData);
		for (var i = 0; i < resultData.length; ++i) {
			commandArray.push(intToByte(resultData[i]));
		}
	};

	/** 挂载方法：在卷标上绘制图片(根据 canvas 画布参数)
	 * 平均灰度阈值（先计算平均灰度，然后大于平均灰度的都算作白色）
	 * BITMAP x,y,width,height,mode,bitmap data
	 * @param res canvas 画布参数
	 * @param x 位图左上角 X 坐标
	 * @param y 位图左上角 Y 坐标
	 * @param mode 位图绘制模式：0 - OVERWRITE、1 - OR、2 - XOR
	 */
	instance.setBitmapAvg = function(res, x = 0, y = 0, mode = 1) {
		var width = parseInt((res.width) / 8 * 8 / 8);
		var height = res.height;
		var imgWidth = res.width;
		var time = 1;
		var temp = res.data.length - width * 32;
		var pointList = [];
		var resultData = [];
		// console.log(width + "--" + height);
		// const data = "BITMAP " + x + "," + y + "," + width + "," + height + "," + mode + ",";
		const data = `BITMAP ${x},${y},${width},${height},${mode},`;
		instance.addCommand(data);
		//console.log(res.data)
		//console.log('---以上是原始数据---');

		let sumRed = 0,
			sumGreen = 0,
			sumBlue = 0;
		let total = height * imgWidth;
		let pix = res.data;
		for (var i = 0; i < pix.length; i += 4) {
			sumRed += pix[i];
			sumGreen += pix[i + 1];
			sumBlue += pix[i + 2];
		}

		let avgRed = parseInt(sumRed / total);
		let avgGreen = parseInt(sumGreen / total);
		let avgBlue = parseInt(sumBlue / total);
		let avgGrayColor = avgRed * 0.299 + avgGreen * 0.587 + avgBlue * 0.114;

		//for循环顺序不要错了，外层遍历高度，内层遍历宽度，因为横向每8个像素点组成一个字节
		for (var y = 0; y < height; y++) {
			for (var x = 0; x < imgWidth; x++) {
				let r = res.data[(y * imgWidth + x) * 4];
				let g = res.data[(y * imgWidth + x) * 4 + 1];
				let b = res.data[(y * imgWidth + x) * 4 + 2];
				let a = res.data[(y * imgWidth + x) * 4 + 3];
				// 像素灰度值
				let grayColor = r * 0.299 + g * 0.587 + b * 0.114;
				//灰度值大于128位 
				//1不打印, 0打印 （参考：佳博标签打印机编程手册tspl）
				if (grayColor > avgGrayColor) {
					pointList.push(1);
				} else {
					pointList.push(0);
				}
			}
		}
		//console.log(pointList)
		for (var i = 0; i < pointList.length; i += 8) {
			var p = pointList[i] * 128 + pointList[i + 1] * 64 + pointList[i + 2] * 32 + pointList[i +
					3] * 16 + pointList[i + 4] * 8 + pointList[i + 5] * 4 + pointList[i + 6] * 2 +
				pointList[i + 7];
			resultData.push(p);
		}
		// console.log('最终数据：', resultData);
		//console.log(resultData)
		for (var i = 0; i < resultData.length; ++i) {
			commandArray.push(intToByte(resultData[i]));
		}
	}

	/** 挂载方法：在卷标上绘制位图(非 BMP 格式图档)
	 * BITMAP x,y,width,height,mode,bitmap data
	 * @param bitmap 16 进制图像数据
	 * @param x 位图左上角 X 坐标
	 * @param y 位图左上角 Y 坐标
	 * @param width 位图的宽度，单位 byte
	 * @param height 位图的高度，单位 dot
	 * @param mode 位图绘制模式：0 - OVERWRITE、1 - OR、2 - XOR
	 */
	instance.bitmap = function(bitmap, x, y, width, height, mode = 1) {
		const data = `BITMAP ${x},${y},${width},${height},${mode},${bitmap}`;
		instance.addCommand(data);
	};

	/** 挂载方法：打印单色 BMP 图片文件
	 * PUTBMP x,y,"filename"
	 * @param filename 欲打印的文件名称(需已下载于打印机缓存)
	 * @param x 水平方向起始点坐标，以点(dot)表示
	 * @param y 垂直方向起始点坐标，以点(dot)表示
	 */
	instance.putbmp = function(filename, x = 0, y = 0) {
		const data = `PUTBMP ${x},${y},"${filename}"`;
		instance.addCommand(data);
	};

	/** 挂载方法：打印单色 PCX 格式图片文件
	 * PUTPCX x,y,"filename"
	 * @param filename 欲打印的文件名称(需已下载于打印机缓存)
	 * @param x 水平方向起始点坐标，以点(dot)表示
	 * @param y 垂直方向起始点坐标，以点(dot)表示
	 */
	instance.putpcx = function(filename, x = 0, y = 0) {
		const data = `PUTPCX ${x},${y},"${filename}"`;
		instance.addCommand(data);
	};

	/** 挂载方法：清除影像缓冲区部分区域的数据
	 * ERASE x_start,y_start,x_width,y_height
	 * @param x_start 清除区域的左上角 X 座标，单位 dot
	 * @param y_start 清除区域的左上角 Y 座标，单位 dot
	 * @param x_width 清除区域宽度，单位 dot
	 * @param y_height 清除区域宽度，单位 dot
	 */
	instance.erase = function(x_start, y_start, x_width, y_height) {
		const data = `ERASE ${x_start},${y_start},${x_width},${y_height}`;
		instance.addCommand(data);
	};

	/** 挂载方法：将指定的区域反相打印
	 * REVERSE x_start,y_start,x_width,y_height
	 * @param x_start 反相区域左上角 X 坐标，单位 dot
	 * @param y_start 反相区域左上角 Y 坐标，单位 dot
	 * @param x_width 反相区域宽度，单位 dot
	 * @param y_height 反相区域高度，单位 dot
	 */
	instance.reverse = function(x_start, y_start, x_width, y_height) {
		const data = `REVERSE ${x_start},${y_start},${x_width},${y_height}`;
		instance.addCommand(data);
	};

	/** 挂载方法：打印字符串
	 * TEXT x,y,"font",rotation,x-multiplication,y-multiplication,"content"
	 * 注: 五号字英文字母仅可打印大写字母 
	 *     若要打印双引号时(")在程序中请使用\["]来打印双引号 
	 *     若要打印 0D(hex)字符时，请在程序中使用\[R]来打印 CR 
	 *     若要打印 0A(hex)字符时，请在程序中使用\[A]来打印 LF
	 * @param content 字符串内容
	 * @param x 文字 X 方向起始点坐标
	 * @param y 文字 Y 方向起始点坐标
	 * @param x_multiplication X 方向放大倍率 1-10
	 * @param y_multiplication Y 方向放大倍率 1-10
	 * @param font 字体名称
				   1 8×12 dot 英数字体
				   2 12×20 dot 英数字体
				   3 16×24 dot 英数字体
				   4 24×32 dot 英数字体
				   5 32×48 dot 英数字体
				   6 14×19 dot 英数字体 OCR-B
				   7 21×27 dot 英数字体 OCR-B
				   8 14×25 dot 英数字体 OCR-A
				   9 9×17 dot 英数字体
				   10 12×24 dot 英数字体
				   TST24.BF2 繁体中文 24×24Font(大五码)
				   TSS24.BF2 简体中文 24×24Font(GB 码)
				   K 韩文 24×24Font(KS 码)
	 * @param rotation 文字旋转角度(顺时针方向)
	 */
	instance.text = function(content, x = 0, y = 0, x_multiplication = 1, y_multiplication = 1, font = 'TSS24.BF2',
		rotation = 0) {
		const data = `TEXT ${x},${y},"${font}",${rotation},${x_multiplication},${y_multiplication},"${content}"`;
		instance.addCommand(data);
	};

	/** 挂载方法：打印二维码
	 * QRCODE x,y,ECC level,cell width,mode,rotation,"data string"
	 * 注: 五号字英文字母仅可打印大写字母 
	 *     若要打印双引号时(")在程序中请使用\["]来打印双引号 
	 *     若要打印 0D(hex)字符时，请在程序中使用\[R]来打印 CR 
	 *     若要打印 0A(hex)字符时，请在程序中使用\[A]来打印 LF
	 * @param data_string 编码的字符串
	 * @param x 二维码水平方向起始点坐标
	 * @param y 二维码垂直方向起始点坐标
	 * @param cell_width 二维码宽度 1-10
	 * @param ecc_level 纠错等级：L - 7%、M - 15%、Q - 25%、R - 30%
	 * @param mode 手动/自动编码：A - Auto、M - Manual
	 * @param rotation 旋转角度(顺时针方向)
	 */
	instance.qrCode = function(data_string, x = 0, y = 0, cell_width = 5, ecc_level = 'L', mode = 'A', rotation = 0) {
		const data = `QRCODE ${x},${y},${ecc_level},${cell_width},${mode},${rotation},"${data_string}"`;
		instance.addCommand(data);
	};

	/**************************************文件管理指令**************************************/

	/** 挂载方法：定义文件可被储存于打印机的 DRAM 中。
	 * 1.Download 程序文件 DOWNLOAD [n,]"FILENAME.BAS"
	 * 2.Download 资料文件 DOWNLOAD [n,]"FILENAME",DATA SIZE,DATA CONTENT...
	 * 下载至打印机的文件可区分为两种:程 序文件及资料文件(包括字符型文件、PCX 图形文件和 BMP 图形文件等)
	 * 注:文件名是大小写敏感的
	 * 文件扩展名必须是 BAS
	 * DRAM 的中的文件在打印机关机后丢失 若要将程序存在打印机内，程序的第一行须加 DOWNLOAD，程序最后一行需以 EOP 做结束
	 * @param filename 储存于打印机中的文件名称
	 * @param data_size 不含文件头的实际文件大小，以字节数计算
	 * @param data_content 下载到打印机的数据
	 * @param n 指定文件存储位置 未指定时文件被储存于 DRAM F:文件存储于 FLASH
	 */
	instance.download = function(filename, data_size, data_content, n = null) {
		let data = '';
		if (filename.endsWith('.BAS')) {
			if (n) {
				data = `DOWNLOAD ${n},"${filename}"`;
			} else {
				data = `DOWNLOAD "${filename}"`;
			}
		} else {
			if (n) {
				data = `DOWNLOAD ${n},"${filename}",${data_size},${data_content}`;
			} else {
				data = `DOWNLOAD ${n},"${filename}",${data_size},${data_content}`;
			}
		}
		instance.addCommand(data);
	};

	/** 挂载方法：程序结束点，需将该指令放在程序的最后一行
	 * EOP
	 */
	instance.eop = function() {
		const data = 'EOP';
		instance.addCommand(data);
	};

	/** 挂载方法：删除储存于打印机内存的文件
	 * KILL "FILENAME"
	 * @param filename 删除的文件名称，注意有大小写。 * 表示删除所有文件
	 */
	instance.kill = function(filename) {
		const data = `KILL "${filename}"`;
		instance.addCommand(data);
	};

	/**************************************返回实例**************************************/
	return instance;
}

/** 标签打印机 */
const gprinterClient = createGprinter();

export default gprinterClient;
